﻿//==============================================================================  
//Copyright (C) 2012-2015 9UN.ORG. All rights reserved. 
//GUID：a27f07fa-7c66-4868-a0df-de2ce4d30efc
//CLR Version: 4.0.30319.18033
//Code Author：Kevin Wang
//Contact：Email(Admin@9un.org),QQ(265382 or 74344)
//Filename：LibVLC_Video_Interop
//Namespace：RuanRang.Media.Core.Internal.Interop.Controls
//Functions：LibVLC_Video_Interop  
//Created by Kevin Wang at 2013/3/3 10:46:49 http://blog.9un.org
//============================================================================== 

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using RuanRang.Media.Core.Common;
using RuanRang.Media.Core.Internal.DataStructures;
using log4net;

namespace RuanRang.Media.Core.Internal.Interop
{
    //Wrapper libvlc video
    //http://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc__video.html
    internal class LibVlcVideoInterop : BaseInterop
    {
        /// <summary>
        /// Initializes static members of the <see cref="LibVlcVideoInterop"/> class.
        /// </summary>
        static LibVlcVideoInterop()
        {
            Logger = LogManager.GetLogger(typeof(LibVlcVideoInterop));
        }

        #region Screen 屏幕
        /// <summary>
        /// Toggle full-screen status on non-embedded video outputs. 
        /// 非嵌入式的视频输出切换全屏状态。
        /// LIBVLC_API void libvlc_toggle_fullscreen (libvlc_media_player_t *p_mi)
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_toggle_fullscreen")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_toggle_fullscreen_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Toggle full-screen status on non-embedded video outputs.
        /// 非嵌入式的视频输出切换全屏状态。
        /// Warning:
        ///     The same limitations applies to this function as to libvlc_set_fullscreen().
        /// 警告：
        ///     相同的限制适用于这个函数libvlc_set_fullscreen。
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player</param>
        public static void libvlc_toggle_fullscreen(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_toggle_fullscreen");
            }
            libvlc_toggle_fullscreen_unmanaged(libvlc_media_player_t);
        }

        /// <summary>
        /// Enable or disable fullscreen.
        /// LIBVLC_API void libvlc_set_fullscreen (libvlc_media_player_t *p_mi, int b_fullscreen)
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="b_fullscreen">The b_fullscreen.</param>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_set_fullscreen")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_set_fullscreen_unmanaged(IntPtr libvlc_media_player_t, int b_fullscreen);

        /// <summary>
        /// Enable or disable fullscreen on a video output.
        /// Warning:
        ///     With most window managers, only a top-level windows can be in full-screen mode.
        ///     Hence, this function will not operate properly if libvlc_media_player_set_xwindow() was used to embed the video in a non-top-level window. 
        ///     In that case, the embedding window must be reparented to the root window before fullscreen mode is enabled. 
        ///     You will want to reparent it back to its normal parent when disabling fullscreen.
        /// 开启或关闭全屏视频输出。
        /// 警告：
        ///     对于大多数窗口管理器，只有一个顶层窗口可以在全屏幕模式下。
        ///     因此，这个功能不会正常工作，如果libvlc_media_player_set_xwindow（）被用来将视频嵌入一个非顶层窗口。
        ///     在这种情况下，必须嵌入窗口的父到根窗口前启用全屏模式。
        ///     你会想reparent回到其正常的父母时，禁用全屏。
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player</param>
        /// <param name="b_fullscreen">boolean for fullscreen status</param>
        public static void libvlc_set_fullscreen(IntPtr libvlc_media_player_t, int b_fullscreen)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_set_fullscreen");
            }
            libvlc_set_fullscreen_unmanaged(libvlc_media_player_t, b_fullscreen);
        }

        /// <summary>
        /// Get current fullscreen status. 
        /// LIBVLC_API int 	libvlc_get_fullscreen (libvlc_media_player_t *p_mi)
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_get_fullscreen")]
        [SuppressUnmanagedCodeSecurity]
        private static extern int libvlc_get_fullscreen_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Enable or disable fullscreen on a video output.
        /// Get current fullscreen status.
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player.</param>
        /// <returns>the fullscreen status (boolean)</returns>
        public static int libvlc_get_fullscreen(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_get_fullscreen");
            }
            return libvlc_get_fullscreen_unmanaged(libvlc_media_player_t);
        }

        #endregion

        #region Key And Mouse 键和鼠标
        /// <summary>
        /// Enable or disable key press events handling, according to the LibVLC hotkeys configuration.
        /// LIBVLC_API void libvlc_video_set_key_input (libvlc_media_player_t *p_mi, unsigned on)
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="on">The on.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_set_key_input")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_video_set_key_input_unmanaged(IntPtr libvlc_media_player_t, uint on);

        /// <summary>
        /// Enable or disable key press events handling, according to the LibVLC hotkeys configuration.
        /// By default and for historical reasons, keyboard events are handled by the LibVLC video widget.
        /// Note:
        ///     On X11, there can be only one subscriber for key press and mouse click events per window.
        ///     If your application has subscribed to those events for the X window ID of the video widget,
        ///     then LibVLC will not be able to handle key presses and mouse clicks in any case.
        /// Warning:
        ///     This function is only implemented for X11 and Win32 at the moment.
        /// 启用或禁用按键事件处理，根据的LibVLC热键配置。
        /// 默认情况下，由于历史的原因，处理键盘事件的LibVLC视频小工具。
        /// 注意：
        ///     在X11上，只能有一个用户，每个窗口的按键和鼠标点击事件。
        ///     如果你的应用程序已经订阅了这些事件的视频窗口小部件的X窗口ID，
        ///     LibVLC将不能够在任何情况下，处理按键和鼠标点击。
        /// 警告：
        ///     此功能只有X11和Win32实现的时刻。
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player</param>
        /// <param name="on">true to handle key press events, false to ignore them.</param>
        public static void libvlc_video_set_key_input(IntPtr libvlc_media_player_t, uint on)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_key_input");
            }
            libvlc_video_set_key_input_unmanaged(libvlc_media_player_t, on);
        }

        /// <summary>
        /// Enable or disable mouse click events handling. 
        /// LIBVLC_API void libvlc_video_set_mouse_input (libvlc_media_player_t *p_mi, unsigned on)
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="on">The on.</param>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_set_mouse_input")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_video_set_mouse_input_unmanaged(IntPtr libvlc_media_player_t, uint on);

        /// <summary>
        /// Enable or disable mouse click events handling. 
        /// By default, those events are handled. This is needed for DVD menus to work,
        /// as well as a few video filters such as "puzzle".
        /// See also:
        ///     libvlc_video_set_key_input().
        /// Warning:
        ///     This function is only implemented for X11 and Win32 at the moment.
        /// 启用或禁用鼠标点击事件处理。
        /// 默认情况下，这些事件的处理方式。这是必要的DVD菜单，
        /// 以及一些视频过滤器，如 “puzzle”。
        /// 参见：
        ///     libvlc_video_set_key_input的（）。
        /// 警告：
        ///     目前此功能只有X11和Win32实现。
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player</param>
        /// <param name="on">true to handle mouse click events, false to ignore them.</param>
        public static void libvlc_video_set_mouse_input(IntPtr libvlc_media_player_t, uint on)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_mouse_input");
            }
            libvlc_video_set_mouse_input_unmanaged(libvlc_media_player_t, on);
        }

        /// <summary>
        /// LIBVLC_API int libvlc_video_get_cursor (libvlc_media_player_t *p_mi, unsigned num, int *px, int *py)
        /// Get the mouse pointer coordinates over a video.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="num">The num.</param>
        /// <param name="px">The px.</param>
        /// <param name="py">The py.</param>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_cursor")]
        [SuppressUnmanagedCodeSecurity]
        private static extern int libvlc_video_get_cursor_unmanaged(IntPtr libvlc_media_player_t, uint num, out int px, out int py);

        /// <summary>
        /// Get the mouse pointer coordinates over a video.
        /// Coordinates are expressed in terms of the decoded video resolution, not in terms of pixels on the screen/viewport (to get the latter, you can query your windowing system directly).
        /// Either of the coordinates may be negative or larger than the corresponding dimension of the video, if the cursor is outside the rendering area.
        /// Warning:
        ///     The coordinates may be out-of-date if the pointer is not located on the video rendering area. LibVLC does not track the pointer if it is outside of the video widget.
        /// Note:
        ///     LibVLC does not support multiple pointers (it does of course support multiple input devices sharing the same pointer) at the moment.
        /// 获取鼠标指针在一个视频上的坐标。
        /// 坐标表示在解码后的视频分辨率方面，而不是在像素方面在屏幕上/视口（后者，你可以直接查询您的窗口系统）。
        /// 任一的坐标可以是负的或大于相应的维的视频，如果光标以外的描画区域。
        /// 警告：
        ///     的坐标可以是日期如果指针没有位于视频渲染区域。 LibVLC不跟踪的指针，如果是外部的视频小工具。
        /// 注意：
        ///     目前LibVLC的不支持多个指针（它当然支持多种输入设备共享相同的指针）。
        /// </summary>
        /// <param name="libvlc_media_player_t">media player.</param>
        /// <param name="num">number of the video (starting from, and most commonly 0).</param>
        /// <param name="px">pointer to get the abscissa [OUT].</param>
        /// <param name="py">pointer to get the ordinate [OUT].</param>
        /// <returns>0 on success, -1 if the specified video does not exist.</returns>
        public static int libvlc_video_get_cursor(IntPtr libvlc_media_player_t, uint num, out int px, out int py)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_cursor");
            }
            return libvlc_video_get_cursor_unmanaged(libvlc_media_player_t, num, out px, out py);
        }

        #endregion

        #region Size 大小
        /// <summary>
        /// LIBVLC_API int libvlc_video_get_size (libvlc_media_player_t *p_mi, unsigned num, unsigned *px, unsigned *py)
        /// Get the pixel dimensions of a video. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="num">The num.</param>
        /// <param name="px">The px.</param>
        /// <param name="py">The py.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_size")]
        [SuppressUnmanagedCodeSecurity]
        private static extern int libvlc_video_get_size_unmanaged(IntPtr libvlc_media_player_t, uint num, out uint px, out uint py);

        /// <summary>
        /// Get the pixel dimensions of a video.
        /// </summary>
        /// <param name="libvlc_media_player_t">media player.</param>
        /// <param name="num">number of the video (starting from, and most commonly 0)</param>
        /// <param name="px">pointer to get the pixel width [OUT]</param>
        /// <param name="py">pointer to get the pixel height [OUT]</param>
        /// <returns>0 on success, -1 if the specified video does not exist</returns>
        public static int libvlc_video_get_size(IntPtr libvlc_media_player_t, uint num, out uint px, out uint py)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_size");
            }
            return libvlc_video_get_size_unmanaged(libvlc_media_player_t, num, out px, out py);
        }

        /// <summary>
        /// LIBVLC_DEPRECATED LIBVLC_API int libvlc_video_get_height (libvlc_media_player_t *p_mi)
        /// Get current video height. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_height")]
        [SuppressUnmanagedCodeSecurity]
        private static extern int libvlc_video_get_height_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Get current video height.
        /// Deprecated:
        ///     Use libvlc_video_get_size() instead.
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player.</param>
        /// <returns>the video pixel height or 0 if not applicable</returns>
        [Obsolete("Don't use Old method, Use libvlc_video_get_size() instead.", true)]
        public static int libvlc_video_get_height(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_height");
            }
            return libvlc_video_get_height_unmanaged(libvlc_media_player_t);
        }

        /// <summary>
        /// LIBVLC_DEPRECATED LIBVLC_API int 	libvlc_video_get_width (libvlc_media_player_t *p_mi)
        /// Get current video width. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_width")]
        [SuppressUnmanagedCodeSecurity]
        private static extern int libvlc_video_get_width_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Get current video width.
        /// Deprecated:
        ///     Use libvlc_video_get_size() instead.
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player..</param>
        /// <returns>the video pixel width or 0 if not applicable</returns>
        [Obsolete("Don't use Old method, Use libvlc_video_get_size() instead.", true)]
        public static int libvlc_video_get_width(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_width");
            }
            return libvlc_video_get_width_unmanaged(libvlc_media_player_t);
        }
        #endregion

        #region Scale
        /// <summary>
        /// LIBVLC_API float libvlc_video_get_scale (libvlc_media_player_t *p_mi)
        /// Get the current video scaling factor. 
        /// 获取当前视频的缩放因子
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_scale")]
        [SuppressUnmanagedCodeSecurity]
        private static extern float libvlc_video_get_scale_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Get the current video scaling factor.
        /// 获取当前视频的缩放因子
        /// See also libvlc_video_set_scale().
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player.</param>
        /// <returns>the currently configured zoom factor, or 0. if the video is set to fit to the output window/drawable automatically.</returns>
        public static float libvlc_video_get_scale(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_scale");
            }
            return libvlc_video_get_scale_unmanaged(libvlc_media_player_t);
        }

        /// <summary>
        /// LIBVLC_API void libvlc_video_set_scale (libvlc_media_player_t *p_mi, float f_factor)
        /// Set the video scaling factor. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="f_factor">The f_factor.</param>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_set_scale")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_video_set_scale_unmanaged(IntPtr libvlc_media_player_t, float f_factor);

        /// <summary>
        /// Set the video scaling factor.
        /// 设置当前视频的缩放因子
        /// That is the ratio of the number of pixels on screen to the number of pixels in the original decoded video in each dimension. 
        /// Zero is a special value; it will adjust the video to the output window/drawable (in windowed mode) or the entire screen.
        /// Note that not all video outputs support scaling.
        /// 这是在屏幕上的像素的数量在原来的解码后的视频在每个维度上的像素的数量的比率。
        /// 零是一个特殊值，它会自动调整视频输出窗口/绘制（在窗口模式下）或整个屏幕。
        /// 请注意，不是所有的视频​​输出支持缩放。
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player.</param>
        /// <param name="f_factor">the scaling factor, or zero.</param>
        public static void libvlc_video_set_scale(IntPtr libvlc_media_player_t, float f_factor)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_scale");
            }
            libvlc_video_set_scale_unmanaged(libvlc_media_player_t, f_factor);
        }

        #endregion

        #region Aspect ratio 高宽比

        /// <summary>
        /// Libvlc_video_get_aspect_ratio_unmanageds the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>StringBuilder.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_aspect_ratio")]
        [SuppressUnmanagedCodeSecurity]
        private static extern string libvlc_video_get_aspect_ratio_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Get current video aspect ratio.
        /// 获取当前视频的高宽比
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player.</param>
        /// <returns>the video aspect ratio or NULL if unspecified (the result must be released with free() or libvlc_free()).</returns>
        public static string libvlc_video_get_aspect_ratio(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_aspect_ratio");
            }
            // TODO: libvlc tells to free memory. but how?
            var value = libvlc_video_get_aspect_ratio_unmanaged(libvlc_media_player_t);
            return value;
        }

        /// <summary>
        /// LIBVLC_API void libvlc_video_set_aspect_ratio (libvlc_media_player_t *p_mi, const char *psz_aspect)
        /// Set new video aspect ratio.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="psz_aspect">The psz_aspect.</param>
        [DllImport("libvlc", ExactSpelling = true, CharSet = CharSet.Ansi, EntryPoint = "libvlc_video_set_aspect_ratio")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_video_set_aspect_ratio_unmanaged(IntPtr libvlc_media_player_t, IntPtr psz_aspect);

        /// <summary>
        /// Set new video aspect ratio.
        /// 设置视频的高宽比
        /// Note:
        ///     Invalid aspect ratios are ignored.
        ///     无效的高宽比将会被忽略
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player.</param>
        /// <param name="type">new video aspect-ratio or NULL to reset to default</param>
        public static void libvlc_video_set_aspect_ratio(IntPtr libvlc_media_player_t, VideoAspectRatioType type)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_aspect_ratio");
            }
            var vType = VideoAspectRatioList.Get(type);
            var pType = IntPtr.Zero;
            try
            {
                var bytes = Encoding.UTF8.GetBytes(vType);
                //
                pType = Marshal.AllocHGlobal(bytes.Length + 1);
                Marshal.Copy(bytes, 0, pType, bytes.Length);
                Marshal.WriteByte(pType, bytes.Length, 0);
                //
                libvlc_video_set_aspect_ratio_unmanaged(libvlc_media_player_t, pType);
            }
            finally
            {
                if (pType != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pType);
                }
            }
        }

        #endregion

        #region SPU 字幕
        /// <summary>
        /// LIBVLC_API int libvlc_video_get_spu (libvlc_media_player_t *p_mi)
        /// Get current video subtitle. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_spu")]
        [SuppressUnmanagedCodeSecurity]
        private static extern int libvlc_video_get_spu_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Get current video subtitle
        /// 获取当前视频的字幕
        /// </summary>
        /// <param name="libvlc_media_player_t">The the media player.</param>
        /// <returns>the video subtitle selected, or -1 if none</returns>
        public static int libvlc_video_get_spu(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_spu");
            }
            return libvlc_video_get_spu_unmanaged(libvlc_media_player_t);
        }

        /// <summary>
        /// Set new video subtitle
        /// 设置当前视频的字幕
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="spu">The spu.</param>
        /// <returns>Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_set_spu")]
        [SuppressUnmanagedCodeSecurity]
        private static extern Int32 libvlc_video_set_spu_unmanaged(IntPtr libvlc_media_player_t, int spu);

        /// <summary>
        /// Set new video subtitle. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The the media player.</param>
        /// <param name="spu">video subtitle track to select (i_id from track description)</param>
        /// <returns>0 on success, -1 if out of range</returns>
        public static Int32 libvlc_video_set_spu(IntPtr libvlc_media_player_t, int spu)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_spu");
            }
            return libvlc_video_set_spu_unmanaged(libvlc_media_player_t, spu);
        }

        /// <summary>
        /// LIBVLC_API int libvlc_video_get_spu_count(libvlc_media_player_t * p_mi) 	
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_spu_count")]
        [SuppressUnmanagedCodeSecurity]
        private static extern Int32 libvlc_video_get_spu_count_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Get the number of available video subtitles.
        /// </summary>
        /// <param name="libvlc_media_player_t">the media player.</param>
        /// <returns>the number of available video subtitles</returns>
        public static Int32 libvlc_video_get_spu_count(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_spu_count");
            }
            return libvlc_video_get_spu_count_unmanaged(libvlc_media_player_t);
        }

        /// <summary>
        /// LIBVLC_API libvlc_track_description_t * 	libvlc_video_get_spu_description (libvlc_media_player_t *p_mi)
        /// Get the description of available video subtitles. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_spu_description")]
        [SuppressUnmanagedCodeSecurity]
        private static extern IntPtr libvlc_video_get_spu_description_unmanaged(IntPtr libvlc_media_player_t);

        /// <summary>
        /// Get the description of available video subtitles.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <returns>list containing description of available video subtitles</returns>
        public static libvlc_track_description_t libvlc_video_get_spu_description(IntPtr libvlc_media_player_t)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_spu_description");
            }
            var des = libvlc_video_get_spu_description_unmanaged(libvlc_media_player_t);
            var structure = (libvlc_track_description_t)Marshal.PtrToStructure(des, typeof(libvlc_track_description_t));
            return structure;
        }
        #endregion

        #region Snapshot
        /// <summary>
        /// Libvlc_video_take_snapshot_unmanageds the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="num">The num.</param>
        /// <param name="filePath">The file path.</param>
        /// <param name="i_width">The i_width.</param>
        /// <param name="i_height">The i_height.</param>
        /// <returns>Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_take_snapshot")]
        [SuppressUnmanagedCodeSecurity]
        private static extern Int32 libvlc_video_take_snapshot_unmanaged(IntPtr libvlc_media_player_t, UInt32 num, IntPtr filePath, UInt32 i_width, UInt32 i_height);

        /// <summary>
        /// Take a snapshot of the current video window
        /// If i_width AND i_height is 0, original size is used. If i_width XOR i_height is 0, original aspect-ratio is preserved
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="num">The num.</param>
        /// <param name="filePath">The file path.</param>
        /// <param name="i_width">The i_width.</param>
        /// <param name="i_height">The i_height.</param>
        /// <returns>Int32.</returns>
        public static Int32 libvlc_video_take_snapshot(IntPtr libvlc_media_player_t, UInt32 num, IntPtr filePath, UInt32 i_width, UInt32 i_height)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_take_snapshot");
            }
            return libvlc_video_take_snapshot_unmanaged(libvlc_media_player_t, num, filePath, i_width, i_height);
        }
        #endregion

        #region Logo
        /// <summary>
        /// LIBVLC_API int 	libvlc_video_get_logo_int (libvlc_media_player_t *p_mi, unsigned option)
        /// Get integer logo option. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_logo_int")]
        [SuppressUnmanagedCodeSecurity]
        private static extern int libvlc_video_get_logo_int_unmanaged(IntPtr libvlc_media_player_t, uint option);
        /// <summary>
        /// Get integer logo option.
        /// </summary>
        /// <param name="libvlc_media_player_t">libvlc media player instance.</param>
        /// <param name="option">logo option to get, values of libvlc_video_logo_option_t.</param>
        /// <returns>System.Int32.</returns>
        public static int libvlc_video_get_logo_int(IntPtr libvlc_media_player_t, VideoLogoOption option)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_logo_int");
            }
            return libvlc_video_get_logo_int_unmanaged(libvlc_media_player_t, (uint)option);
        }

        /// <summary>
        /// LIBVLC_API void 	libvlc_video_set_logo_int (libvlc_media_player_t *p_mi, unsigned option, int value)
        /// Set logo option as integer. 
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <param name="value">The value.</param>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_set_logo_int")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_video_set_logo_int_unmanaged(IntPtr libvlc_media_player_t, uint option, int value);

        /// <summary>
        /// Libvlc_video_set_logo_ints the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <param name="value">The value.</param>
        public static void libvlc_video_set_logo_int(IntPtr libvlc_media_player_t, VideoLogoOption option, int value)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_logo_int");
            }
            libvlc_video_set_logo_int_unmanaged(libvlc_media_player_t, (uint)option, value);
        }

        //LIBVLC_API void 	libvlc_video_set_logo_string (libvlc_media_player_t *p_mi, unsigned option, const char *psz_value)
        /// <summary>
        /// Set logo option as string.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <param name="psz_value">The psz_value.</param>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_set_logo_string")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_video_set_logo_string_unmanaged(IntPtr libvlc_media_player_t, uint option, IntPtr psz_value);

        /// <summary>
        /// Libvlc_video_set_logo_strings the specified libvlc_media_player_t.
        /// Set logo option as string.
        /// Options 
        ///   that take a different type value are ignored.
        /// </summary>
        /// <param name="libvlc_media_player_t">libvlc media player instance.</param>
        /// <param name="option">that take a different type value are ignored.</param>
        /// <param name="value">logo option value</param>
        public static void libvlc_video_set_logo_string(IntPtr libvlc_media_player_t, VideoLogoOption option, string value)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_logo_string");
            }
            var pszValue = IntPtr.Zero;
            try
            {
                var bytes = Encoding.UTF8.GetBytes(value);
                //
                pszValue = Marshal.AllocHGlobal(bytes.Length + 1);
                Marshal.Copy(bytes, 0, pszValue, bytes.Length);
                Marshal.WriteByte(pszValue, bytes.Length, 0);
                //
                libvlc_video_set_logo_string_unmanaged(libvlc_media_player_t, (uint)option, pszValue);
            }
            finally
            {
                if (pszValue != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pszValue);
                }
            }
        }

        //    Set logo option as string. 
        #endregion

        #region Adjust
        /// <summary>
        /// Libvlc_video_set_adjust_ints the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <param name="value">The value.</param>
        /// <returns>IntPtr.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_set_adjust_int")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_video_set_adjust_int_unmanaged(IntPtr libvlc_media_player_t, libvlc_video_adjust_option_t option, int value);

        /// <summary>
        /// Libvlc_video_set_adjust_ints the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <param name="value">The value.</param>
        public static void libvlc_video_set_adjust_int(IntPtr libvlc_media_player_t, libvlc_video_adjust_option_t option, int value)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_adjust_int");
            }
            libvlc_video_set_adjust_int_unmanaged(libvlc_media_player_t, option, value);
        }

        /// <summary>
        /// Libvlc_video_get_adjust_ints the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <returns>System.Int32.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_adjust_int")]
        [SuppressUnmanagedCodeSecurity]
        private static extern int libvlc_video_get_adjust_int_unmanaged(IntPtr libvlc_media_player_t, libvlc_video_adjust_option_t option);

        /// <summary>
        /// Libvlc_video_set_adjust_ints the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <returns>System.Int32.</returns>
        public static int libvlc_video_get_adjust_int(IntPtr libvlc_media_player_t, libvlc_video_adjust_option_t option)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_adjust_int");
            }
            return libvlc_video_get_adjust_int_unmanaged(libvlc_media_player_t, option);
        }

        /// <summary>
        /// Libvlc_video_set_adjust_floats the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <param name="value">The value.</param>
        /// <returns>IntPtr.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_set_adjust_float")]
        [SuppressUnmanagedCodeSecurity]
        private static extern void libvlc_video_set_adjust_float_unmanaged(IntPtr libvlc_media_player_t, libvlc_video_adjust_option_t option, float value);

        /// <summary>
        /// Libvlc_video_set_adjust_floats the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <param name="value">The value.</param>
        public static void libvlc_video_set_adjust_float(IntPtr libvlc_media_player_t, libvlc_video_adjust_option_t option, float value)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_set_adjust_float");
            }
            libvlc_video_set_adjust_float_unmanaged(libvlc_media_player_t, option, value);
        }

        /// <summary>
        /// Libvlc_video_get_adjust_floats the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <returns>System.Single.</returns>
        [DllImport("libvlc", ExactSpelling = true, EntryPoint = "libvlc_video_get_adjust_float")]
        [SuppressUnmanagedCodeSecurity]
        private static extern float libvlc_video_get_adjust_float_unmanaged(IntPtr libvlc_media_player_t, libvlc_video_adjust_option_t option);

        /// <summary>
        /// Libvlc_video_get_adjust_floats the specified libvlc_media_player_t.
        /// </summary>
        /// <param name="libvlc_media_player_t">The libvlc_media_player_t.</param>
        /// <param name="option">The option.</param>
        /// <returns>System.Single.</returns>
        public static float libvlc_video_get_adjust_float(IntPtr libvlc_media_player_t, libvlc_video_adjust_option_t option)
        {
            if (CallTraceEnabled)
            {
                TraceCall("libvlc_video_get_adjust_float");
            }
            return libvlc_video_get_adjust_float_unmanaged(libvlc_media_player_t, option);
        }

        #endregion

        /// <summary>
        /// Set new video subtitle.
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <param name="subtitleFile">New video subtitle file</param>
        /// <returns>0 on success, -1 if out of range</returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern int libvlc_video_set_subtitle_file(IntPtr playerInstance, string subtitleFile);

        /// <summary>
        /// Get the description of available titles.
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <returns>Success status</returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr libvlc_video_get_title_description(IntPtr playerInstance);

        /// <summary>
        /// Get the description of available chapters for specific title.
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <param name="title">Selected title</param>
        /// <returns>List containing description of available chapter for title title</returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr libvlc_video_get_chapter_description(IntPtr playerInstance, int title);

        // libvlc_video_get_crop_geometry
        // libvlc_video_set_crop_geometry
        // libvlc_video_get_teletext
        // libvlc_video_set_teletext
        // libvlc_toggle_teletext

        /// <summary>
        /// Get number of available video tracks.
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <returns>Number of available video tracks</returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern int libvlc_video_get_track_count(IntPtr playerInstance);

        /// <summary>
        /// Get the description of available video tracks.
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <returns>List with description of available video tracks, or NULL on error</returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr libvlc_video_get_track_description(IntPtr playerInstance);

        /// <summary>
        /// Get current video track.
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <returns>Video track or -1 if none</returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern int libvlc_video_get_track(IntPtr playerInstance);

        /// <summary>
        /// Set video track.
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <param name="track">Track</param>
        /// <returns>0 on success, -1 if out of range</returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern int libvlc_video_set_track(IntPtr playerInstance, int track);


        /// <summary>
        /// Enable or disable deinterlace filter
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <param name="mode">Type of deinterlace filter, NULL to disable</param>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern void libvlc_video_set_deinterlace(IntPtr playerInstance, string mode);

        /// <summary>
        /// Get an integer marquee option value
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <param name="option">Marq option to get</param>
        /// <returns></returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern int libvlc_video_get_marquee_int(IntPtr playerInstance, libvlc_video_marquee_option_t option);

        /// <summary>
        /// Get a string marquee option value
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <param name="option">Marq option to get</param>
        /// <returns></returns>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr libvlc_video_marquee_string(IntPtr playerInstance, uint option);

        /// <summary>
        /// Enable, disable or set an integer marquee option
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <param name="option">Marq option to set</param>
        /// <param name="value">Marq option value</param>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern void libvlc_video_set_marquee_int(IntPtr playerInstance, uint option, int value);

        /// <summary>
        /// Set a marquee string option
        /// </summary>
        /// <param name="playerInstance">Media player instance</param>
        /// <param name="option">Marq option to set</param>
        /// <param name="value">Marq option value</param>
        [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
        public static extern void libvlc_video_set_marquee_string(IntPtr playerInstance, uint option, string value);

    }
}
